/**
 *  Created on  : 08/06/2012
 *  Author      : Ing. Javier Silva Pérez - [javier]
 *  Description :
 *  	
 */
package cinvestav.cryptography.pki.android.key;

import java.math.BigInteger;

import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;

import cinvestav.cryptography.pki.android.ec.ECDomainParameters;
import cinvestav.cryptography.pki.android.ec.ECPointF2m;
import cinvestav.cryptography.pki.android.ec.ECPointFp;
import cinvestav.cryptography.pki.android.exception.AndroidCryptoUtilsException;

/**
 * @author Ing. Javier Silva Pérez - [javier]
 * @since 08/06/2012
 * @version 1.0
 */
public class ECKeyPair {

	private ECPrivateKey privateKey;
	private ECPublicKey publicKey;

	/**
	 * ECKeyPair constructor, which receives both public and privateKeys
	 * 
	 * @param privateKey
	 *            Private part of the key
	 * @param publicKey
	 *            Public part of the key
	 * @throws AndroidCryptoUtilsException
	 *             If the fields of the keys and points are not the same
	 */
	public ECKeyPair(ECPrivateKey privateKey, ECPublicKey publicKey)
			throws AndroidCryptoUtilsException {
		this.privateKey = new ECPrivateKey(privateKey);

		Object publicPoint = publicKey.getQ();
		if (publicPoint instanceof ECPointFp) {
			this.publicKey = new ECPublicKey(publicKey.getParams(),
					publicKey.getQFp());
		} else if (publicPoint instanceof ECPointF2m) {
			this.publicKey = new ECPublicKey(publicKey.getParams(),
					publicKey.getQF2m());
		}
	}

	/**
	 * Constructor that receives each parameter for construct the key over Fp
	 * 
	 * @param parameters
	 *            Curve parameters
	 * @param privateKeyPart
	 *            Private part of the key (BigInter)
	 * @param publicKeyPoint
	 *            Point that represents the public part of the key
	 * @throws AndroidCryptoUtilsException
	 *             If the point and the parameters does not correspond to the
	 *             same field
	 */
	public ECKeyPair(ECDomainParameters parameters, BigInteger privateKeyPart,
			ECPointFp publicKeyPoint) throws AndroidCryptoUtilsException {
		this.privateKey = new ECPrivateKey(parameters, privateKeyPart);
		this.publicKey = new ECPublicKey(parameters, publicKeyPoint);
	}

	/**
	 * Constructor that receives each parameter for construct the key over Fp
	 * 
	 * @param parameters
	 *            Curve parameters
	 * @param privateKeyPart
	 *            Private part of the key (BigInter)
	 * @param publicKeyPoint
	 *            Point that represents the public part of the key
	 * @throws AndroidCryptoUtilsException
	 *             If the point and the parameters does not correspont to the
	 *             same field
	 */
	public ECKeyPair(ECDomainParameters parameters, BigInteger privateKeyPart,
			ECPointF2m publicKeyPoint) throws AndroidCryptoUtilsException {
		this.privateKey = new ECPrivateKey(parameters, privateKeyPart);
		this.publicKey = new ECPublicKey(parameters, publicKeyPoint);
	}

	/**
	 * Parse SpongyCastle AsymmetricCipherKeyPair to EC Key Pair, the result of
	 * the parse will returned
	 * 
	 * @param keyPair
	 *            EC Key Pair to be parsed
	 * @return The new ECKeyPair resulting of the parse
	 * @throws AndroidCryptoUtilsException
	 *             if the key pair does not correspond to valid EC Keys
	 *             parameters
	 */
	public static ECKeyPair parse(AsymmetricCipherKeyPair keyPair)
			throws AndroidCryptoUtilsException {
		if (keyPair.getPrivate() instanceof ECPrivateKeyParameters
				&& keyPair.getPublic() instanceof ECPublicKeyParameters) {
			ECKeyPair res = new ECKeyPair(
					ECPrivateKey.parse((ECPrivateKeyParameters) keyPair
							.getPrivate()),
					ECPublicKey.parse((ECPublicKeyParameters) keyPair
							.getPublic()));
			return res;
		}
		throw new AndroidCryptoUtilsException(
				"ECKeyPair parse error: KeyPair parameter does not correspont to valid EC Keys values");
	}

	/**
	 * Parse the calling object to SpongyCastle AsymmetricCipherKeyPair
	 * representation
	 * 
	 * @return New AsymmetricCipherKeyPair object with the key values of the
	 *         current object
	 */
	public AsymmetricCipherKeyPair parseTo() {
		AsymmetricCipherKeyPair tempPair = new AsymmetricCipherKeyPair(
				this.publicKey.parseToECPublicKeyParameters(),
				this.privateKey.parseToECPrivateKeyParameters());
		return tempPair;

	}

}
